From fd188b183270ebc0a8bc1d9fd2e7a1713a6fcccb Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 23 Jan 2007 11:48:29 -0700 Subject: [PATCH] [IA64] Fix broken switch stack unw_init_running() needs to be called later in the OS INIT handler to prevent the switch stack from being broken by calls to other functions. Signed-off-by: Akio Takebe --- xen/arch/ia64/linux-xen/mca.c | 60 ++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/xen/arch/ia64/linux-xen/mca.c b/xen/arch/ia64/linux-xen/mca.c index 8715ef1d5e..faa73e6672 100644 --- a/xen/arch/ia64/linux-xen/mca.c +++ b/xen/arch/ia64/linux-xen/mca.c @@ -684,16 +684,7 @@ fetch_min_state (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_sta #ifdef XEN static spinlock_t init_dump_lock = SPIN_LOCK_UNLOCKED; static spinlock_t show_stack_lock = SPIN_LOCK_UNLOCKED; - -static void -save_ksp (struct unw_frame_info *info, void *arg) -{ - current->arch._thread.ksp = (__u64)(info->sw) - 16; - wmb(); -} - -/* FIXME */ -int try_crashdump(struct pt_regs *a) { return 0; } +static atomic_t num_stopped_cpus = ATOMIC_INIT(0); #define CPU_FLUSH_RETRY_MAX 5 static void @@ -716,6 +707,35 @@ init_cache_flush (void) } printk("\nPAL cache flush failed. status=%ld\n",rval); } + +static void inline +save_ksp (struct unw_frame_info *info) +{ + current->arch._thread.ksp = (__u64)(info->sw) - 16; + wmb(); + init_cache_flush(); +} + +static void +freeze_cpu_osinit (struct unw_frame_info *info, void *arg) +{ + save_ksp(info); + atomic_inc(&num_stopped_cpus); + printk("%s: CPU%d init handler done\n", + __FUNCTION__, smp_processor_id()); + for (;;) + local_irq_disable(); +} + +/* FIXME */ +static void +try_crashdump(struct unw_frame_info *info, void *arg) +{ + save_ksp(info); + printk("\nINIT dump complete. Please reboot now.\n"); + for (;;) + local_irq_disable(); +} #endif /* XEN */ static void @@ -741,7 +761,8 @@ init_handler_platform (pal_min_state_area_t *ms, show_min_state(ms); #ifdef XEN - printk("Backtrace of current vcpu (vcpu_id %d)\n", current->vcpu_id); + printk("Backtrace of current vcpu (vcpu_id %d of domid %d)\n", + current->vcpu_id, current->domain->domain_id); #else printk("Backtrace of current task (pid %d, %s)\n", current->pid, current->comm); fetch_min_state(ms, pt, sw); @@ -749,20 +770,21 @@ init_handler_platform (pal_min_state_area_t *ms, unw_init_from_interruption(&info, current, pt, sw); ia64_do_show_stack(&info, NULL); #ifdef XEN - unw_init_running(save_ksp, NULL); spin_unlock(&show_stack_lock); - wmb(); - init_cache_flush(); if (spin_trylock(&init_dump_lock)) { #ifdef CONFIG_SMP - udelay(5*1000000); + int other_cpus = num_online_cpus() - 1; + int wait = 1000 * other_cpus; + + while ((atomic_read(&num_stopped_cpus) != other_cpus) && wait--) + udelay(1000); + if (other_cpus && wait < 0) + printk("timeout %d\n", atomic_read(&num_stopped_cpus)); #endif - if (try_crashdump(pt) == 0) - printk("\nINIT dump complete. Please reboot now.\n"); + unw_init_running(try_crashdump, pt); } - printk("%s: CPU%d init handler done\n", - __FUNCTION__, smp_processor_id()); + unw_init_running(freeze_cpu_osinit, NULL); #else /* XEN */ #ifdef CONFIG_SMP /* read_trylock() would be handy... */ -- 2.30.2